package com.hu.system.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.hu.common.utils.StringUtils;
import com.hu.system.domain.StockOutbound;
import com.hu.system.domain.ProductInfo;
import com.hu.system.domain.ShopInfo;
import com.hu.system.service.IProductInfoService;
import com.hu.system.service.IShopInfoService;
import com.hu.system.mapper.StockOutboundMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 备货出库导入监听器
 * 使用无模型读取和手动列映射，支持动态表头识别
 *
 * @author hu-erp
 */
public class StockOutboundImportListener extends AnalysisEventListener<Map<Integer, String>> {

    private static final Logger log = LoggerFactory.getLogger(StockOutboundImportListener.class);

    /**
     * 每隔100条存储数据库
     */
    private static final int BATCH_COUNT = 100;

    private List<StockOutbound> batchList = new ArrayList<>();

    private final IProductInfoService productInfoService;
    private final IShopInfoService shopInfoService;
    private final StockOutboundMapper stockOutboundMapper;
    private final String createBy;
    private final String importRemark;
    private final int expectedHeadRowNumber;
    private final Map<String, Integer> columnMap;

    /** 内存缓存：避免同一请求重复查库 */
    private Map<String, ShopInfo> shopCache = new HashMap<>();
    private Map<String, ProductInfo> productCache = new HashMap<>();
    
    /** 批次内去重缓存：记录已加入批次的订单号+SKU组合，避免批量插入时唯一键冲突 */
    private Map<String, String> batchDuplicateCache = new HashMap<>();

    // 统计信息
    private int successNum = 0;
    private int failureNum = 0;
    private StringBuilder failureMsg = new StringBuilder();
    private int createdProductCount = 0;
    private int updatedProductCount = 0;
    private int createdShopCount = 0;
    private int insertedOutboundCount = 0;  // 新增出库记录数
    private int updatedOutboundCount = 0;   // 更新出库记录数
    private int skippedDuplicateCount = 0;  // 跳过的批次内重复数据数
    private List<String> updatedProductDetails = new ArrayList<>();
    private List<String> skippedDuplicateDetails = new ArrayList<>();  // 跳过的重复数据明细

    public StockOutboundImportListener(IProductInfoService productInfoService,
                                       IShopInfoService shopInfoService,
                                       StockOutboundMapper stockOutboundMapper,
                                       String createBy,
                                       int expectedHeadRowNumber,
                                       Map<String, Integer> columnMap) {
        this.productInfoService = productInfoService;
        this.shopInfoService = shopInfoService;
        this.stockOutboundMapper = stockOutboundMapper;
        this.createBy = createBy;
        this.importRemark = "【导入于 " + com.hu.common.utils.DateUtils.getTime() + "】";
        this.expectedHeadRowNumber = expectedHeadRowNumber;
        this.columnMap = columnMap;
    }

    @Override
    public void invoke(Map<Integer, String> rowData, AnalysisContext context) {
        StockOutbound stockOutbound = null;
        
        try {
            int currentRowIndex = context.readRowHolder().getRowIndex();
            
            if (currentRowIndex <= expectedHeadRowNumber) {
                return;
            }
            
            stockOutbound = mapRowToStockOutbound(rowData);
            if (stockOutbound == null) {
                return;
            }

            // 处理店铺
            if (StringUtils.isEmpty(stockOutbound.getShopName())) {
                failureNum++;
                failureMsg.append("<br/>SKU[" + stockOutbound.getSku() + "]：所属店铺不能为空");
                return;
            }
            
            String currentShopName = stockOutbound.getShopName();
            ShopInfo shop = shopCache.get(currentShopName);
            if (shop == null) {
                // 缓存中没有，查询或创建
                shop = shopInfoService.getOrCreateShopByName(currentShopName, createBy);
                shopCache.put(currentShopName, shop);

                // 统计新建店铺
                if (shop.getCreateBy() != null && shop.getCreateBy().equals(createBy)) {
                    createdShopCount++;
                }
            }
            Long currentShopId = shop.getShopId();
            stockOutbound.setShopId(currentShopId);

            // 校验必填字段
            if (StringUtils.isEmpty(stockOutbound.getStockOrderNo())) {
                failureNum++;
                failureMsg.append("<br/>SKU[" + stockOutbound.getSku() + "]：备货单号不能为空");
                return;
            }

            if (stockOutbound.getOutboundQuantity() == null || stockOutbound.getOutboundQuantity() <= 0) {
                failureNum++;
                failureMsg.append("<br/>SKU[" + stockOutbound.getSku() + "]：备货数量不能为空且必须大于0");
                return;
            }

            if (stockOutbound.getOutboundDate() == null) {
                failureNum++;
                failureMsg.append("<br/>SKU[" + stockOutbound.getSku() + "]：备货日期不能为空");
                return;
            }

            // 处理物流费用
            if (stockOutbound.getLogisticsFee() == null) {
                stockOutbound.setLogisticsFee(BigDecimal.ZERO);
            }

            // 检查产品是否存在，不存在则自动创建
            String productCacheKey = stockOutbound.getSku() + "_" + currentShopId;
            ProductInfo product = productCache.get(productCacheKey);

            if (product == null) {
                com.hu.system.domain.ProductOperationResult operationResult = productInfoService.getOrCreateProduct(
                        stockOutbound.getSku(),
                        stockOutbound.getProductName(),
                        stockOutbound.getSkuAttr(),
                        stockOutbound.getSkuCode(),
                        currentShopId
                );
                product = operationResult.getProduct();
                productCache.put(productCacheKey, product);

                // 统计产品操作
                if (operationResult.getOperationType() == com.hu.system.domain.ProductOperationResult.OperationType.CREATED) {
                    createdProductCount++;
                } else if (operationResult.getOperationType() == com.hu.system.domain.ProductOperationResult.OperationType.UPDATED) {
                    updatedProductCount++;
                    updatedProductDetails.add("SKU[" + stockOutbound.getSku() + "]" + operationResult.getUpdateDescription());
                }
            }

            // 从产品信息中补充字段
            if (product != null) {
                if (StringUtils.isEmpty(stockOutbound.getProductName())) {
                    stockOutbound.setProductName(product.getProductName());
                }
                if (StringUtils.isEmpty(stockOutbound.getSkuAttr())) {
                    stockOutbound.setSkuAttr(product.getSkuAttr());
                }
            }

            // 处理备注
            String remark = "";
            if (StringUtils.isNotEmpty(stockOutbound.getRemark())) {
                remark = stockOutbound.getRemark() + " ";
            }
            remark += importRemark;
            stockOutbound.setRemark(remark.trim());

            // 根据备货单号+SKU查询数据库中是否已存在
            StockOutbound existingRecord = stockOutboundMapper.selectByStockOrderNoAndSku(
                    stockOutbound.getStockOrderNo(), 
                    stockOutbound.getSku()
            );

            if (existingRecord != null) {
                // 数据库中已存在，执行更新操作
                stockOutbound.setUpdateBy(createBy);
                stockOutboundMapper.updateByStockOrderNoAndSku(stockOutbound);
                updatedOutboundCount++;
                successNum++;
            } else {
                // 数据库中不存在，准备批量插入
                // 但先检查当前批次中是否已有相同的订单号+SKU组合
                String duplicateKey = stockOutbound.getStockOrderNo() + "-" + stockOutbound.getSku();
                String detail = "订单号[" + stockOutbound.getStockOrderNo() + "] + SKU[" + stockOutbound.getSku() + "]";
                
                if (batchDuplicateCache.containsKey(duplicateKey)) {
                    // 批次内重复，跳过该记录
                    skippedDuplicateCount++;
                    skippedDuplicateDetails.add(detail);
                    log.warn("跳过批次内重复数据：{}", detail);
                } else {
                    // 批次内不重复，添加到批次列表
                    stockOutbound.setDelFlag("0");
                    stockOutbound.setCreateBy(createBy);
                    batchList.add(stockOutbound);
                    batchDuplicateCache.put(duplicateKey, detail);
                    successNum++;

                    if (batchList.size() >= BATCH_COUNT) {
                        saveData();
                    }
                }
            }

        } catch (Exception e) {
            failureNum++;
            String sku = (stockOutbound != null && stockOutbound.getSku() != null) ? stockOutbound.getSku() : "未知";
            String msg = "<br/>" + (successNum + failureNum) + "、SKU[" + sku + "] 处理失败：";
            failureMsg.append(msg + e.getMessage());
            log.error("导入数据处理失败，SKU: {}", sku, e);
        }
    }

    private StockOutbound mapRowToStockOutbound(Map<Integer, String> rowData) {
        boolean isEmpty = rowData.values().stream().allMatch(v -> v == null || v.trim().isEmpty());
        if (isEmpty) {
            return null;
        }
        
        StockOutbound entity = new StockOutbound();
        entity.setSku(getColumnValueAsText(rowData, "SKU ID", "SKU", "Sku"));
        entity.setProductName(getColumnValue(rowData, "产品名称"));
        entity.setSkuAttr(getColumnValue(rowData, "SKU属性", "Sku属性"));
        entity.setSkuCode(getColumnValueAsText(rowData, "SKU货号", "SKU 货号"));
        entity.setShopName(getColumnValue(rowData, "所属店铺", "店铺"));
        entity.setStockOrderNo(getColumnValue(rowData, "备货单号"));
        entity.setRemark(getColumnValue(rowData, "备注"));
        entity.setOutboundQuantity(parseInteger(getColumnValue(rowData, "备货数量", "出库数量")));
        entity.setLogisticsFee(parseBigDecimal(getColumnValue(rowData, "物流费用")));
        entity.setOutboundDate(parseDate(getColumnValue(rowData, "备货日期", "备货发出日期", "日期", "出库日期")));
        
        if (StringUtils.isEmpty(entity.getSku())) {
            return null;
        }
        
        return entity;
    }
    
    /**
     * 获取列值（支持多个可能的列名）
     */
    private String getColumnValue(Map<Integer, String> rowData, String... possibleColumnNames) {
        for (String columnName : possibleColumnNames) {
            Integer columnIndex = columnMap.get(columnName);
            if (columnIndex != null) {
                String value = rowData.get(columnIndex);
                if (value != null && !value.trim().isEmpty()) {
                    return value.trim();
                }
            }
        }
        return null;
    }
    
    /**
     * 获取文本列值（去除数字格式化）
     * 用于SKU、SKU货号等字段
     */
    private String getColumnValueAsText(Map<Integer, String> rowData, String... possibleColumnNames) {
        String value = getColumnValue(rowData, possibleColumnNames);
        if (value == null) {
            return null;
        }
        
        // 去除数字格式化：千分位逗号和末尾的.00
        value = value.replace(",", "");
        if (value.matches(".*\\.0+$")) {
            value = value.replaceAll("\\.0+$", "");
        }
        
        return value;
    }
    
    private Integer parseInteger(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            return Integer.parseInt(value.trim());
        } catch (Exception e) {
            return null;
        }
    }
    
    private BigDecimal parseBigDecimal(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            return new BigDecimal(value.trim());
        } catch (Exception e) {
            return BigDecimal.ZERO;
        }
    }
    
    private java.util.Date parseDate(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            return com.hu.common.utils.DateUtils.parseDate(value.trim());
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 保存剩余数据
        saveData();
        log.info("所有数据解析完成，成功{}条，失败{}条", successNum, failureNum);
    }

    /**
     * 批量保存数据
     */
    private void saveData() {
        if (!batchList.isEmpty()) {
            int batchSize = batchList.size();
            stockOutboundMapper.batchInsertStockOutbound(new ArrayList<>(batchList));
            insertedOutboundCount += batchSize;
            log.info("批量保存{}条数据到数据库", batchSize);
            batchList.clear();
            // 清空批次去重缓存，为下一批次做准备
            batchDuplicateCache.clear();
        }
    }

    /**
     * 获取导入结果
     */
    public String getResult() {
        StringBuilder resultMsg = new StringBuilder();

        if (failureNum > 0 || skippedDuplicateCount > 0) {
            resultMsg.append("导入完成！成功 " + successNum + " 条");
            if (failureNum > 0) {
                resultMsg.append("，失败 " + failureNum + " 条");
            }
            if (skippedDuplicateCount > 0) {
                resultMsg.append("，跳过重复 " + skippedDuplicateCount + " 条");
            }
        } else {
            resultMsg.append("恭喜您，数据已全部导入成功！共 " + successNum + " 条");
        }

        // 添加出库记录操作统计
        if (insertedOutboundCount > 0 || updatedOutboundCount > 0) {
            resultMsg.append("<br/><br/>【出库记录统计】");
            if (insertedOutboundCount > 0) {
                resultMsg.append("<br/>新增记录：" + insertedOutboundCount + " 条");
            }
            if (updatedOutboundCount > 0) {
                resultMsg.append("<br/>覆盖更新：" + updatedOutboundCount + " 条（根据备货单号+SKU唯一键）");
            }
            if (skippedDuplicateCount > 0) {
                resultMsg.append("<br/>跳过重复：" + skippedDuplicateCount + " 条（导入文件中同一订单号+SKU重复出现）");
            }
        }

        // 添加店铺操作统计
        if (createdShopCount > 0) {
            resultMsg.append("<br/><br/>【店铺处理统计】");
            resultMsg.append("<br/>新建店铺：" + createdShopCount + " 个");
        }

        // 添加产品操作统计
        if (createdProductCount > 0 || updatedProductCount > 0) {
            resultMsg.append("<br/><br/>【产品处理统计】");
            if (createdProductCount > 0) {
                resultMsg.append("<br/>新建产品：" + createdProductCount + " 个");
            }
            if (updatedProductCount > 0) {
                resultMsg.append("<br/>更新产品：" + updatedProductCount + " 个");
                if (!updatedProductDetails.isEmpty()) {
                    resultMsg.append("<br/>更新详情：");
                    int displayCount = Math.min(10, updatedProductDetails.size());
                    for (int i = 0; i < displayCount; i++) {
                        resultMsg.append("<br/>  · " + updatedProductDetails.get(i));
                    }
                    if (updatedProductDetails.size() > 10) {
                        resultMsg.append("<br/>  · ... 还有 " + (updatedProductDetails.size() - 10) + " 条更新");
                    }
                }
            }
        }

        // 添加重复数据明细
        if (skippedDuplicateCount > 0) {
            resultMsg.append("<br/><br/>【跳过重复数据明细】");
            resultMsg.append("<br/>说明：以下数据在导入文件中重复出现（相同订单号+SKU组合），仅保留第一次出现的记录");
            int displayCount = Math.min(10, skippedDuplicateDetails.size());
            for (int i = 0; i < displayCount; i++) {
                resultMsg.append("<br/>  · " + skippedDuplicateDetails.get(i));
            }
            if (skippedDuplicateDetails.size() > 10) {
                resultMsg.append("<br/>  · ... 还有 " + (skippedDuplicateDetails.size() - 10) + " 条重复");
            }
        }

        if (failureNum > 0) {
            resultMsg.append("<br/><br/>【失败明细】");
            resultMsg.append(failureMsg);
        }

        return resultMsg.toString();
    }
}
